:: ------------------------------------------------------------
:: Copyright (c) Microsoft Corporation.  All rights reserved.
:: Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
:: ------------------------------------------------------------

@echo off
setlocal EnableDelayedExpansion

:: This script updates the Windows Fabric trace manifest file
:: Once updated, it shows up as a modified file in Git. Please
:: inspect and commit this file along with your other changes.

if '%1'=='' (
  echo Invalid command line option. Please type %~nx0 /? for help.
  exit /b -1
)

if /I '%1'=='/?' goto :PrintUsage
if /I '%1'=='/h' goto :PrintUsage
if /I '%1'=='/help' goto :PrintUsage
if /I '%1'=='-?' goto :PrintUsage
if /I '%1'=='-h' goto :PrintUsage
if /I '%1'=='-help' goto :PrintUsage

if /I '%1' NEQ '/run' (
  echo Invalid command line option. Please type %~nx0 /? for help.
  exit /b -1
)
set AllowBreakingPerfCounterChanges=false

if /I '%2' EQU '/allowBreakingChangeInCounters' (
    echo Skipping compatibility check of managed performance counter ID. 
	echo This option is meant to allow breaking changes within a release. Please ensure that you do not make breaking changes across releases when using this option.
    set AllowBreakingPerfCounterChanges=true
)

set CurDir=%~dp0

:: Ensure we are running from FabricUnitTests
:: We cannot run it from Git source path since the corext environment
:: doesn't provide  build type (debug/retail) info in its environment.
:: So, we aren't sure if we need to go to debug-amd64\bin\FabricUnitTests or retail-amd64\bin\FabricUnitTests
:: So, executing from the destination directory itself.
echo %CurDir% >%temp%\runtests.curdir.txt
find /I "FabricUnitTests" %temp%\runtests.curdir.txt >nul
set ev=%errorlevel%
del %temp%\runtests.curdir.txt
if %ev% equ 1 goto RunFromFabricUnitTestsDirMsg

set CurDir=%~dp0
:: Remove the last backslash
set CurDir=%CurDir:~0,-1%
for %%d in (%CurDir%) do set ParentDir=%%~dpd

set BIN_PATH=%ParentDir:~0,-1%%

set BINARIES_DIR=%BIN_PATH%\FabricUnitTests
set path=%path%;%BINARIES_DIR%

:: Run
call :UpdateGeneratedFiles
if "!UpdateGeneratedFilesReturn!"=="false" exit /b 1

endlocal
goto :EOF

:: ===========================================================================
:: Updates autogenerated files
::
:UpdateGeneratedFiles
set MANIFEST_FILE_DIFF=%BINARIES_DIR%\ManifestFileDiff.txt
set CONFIG_FILE_DIFF=%BINARIES_DIR%\ConfigFileDiff.txt
set COUNTER_MANIFEST_FILE_DIFF=%BINARIES_DIR%\CounterManifestFileDiff.txt



set UpdateTraceManifestFileReturn=true
call :UpdateTraceManifestFile
if "!UpdateTraceManifestFileReturn!"=="false" (
    set UpdateGeneratedFilesReturn=false
    goto :EOF
)

set UpdateConfigManifestFileReturn=true
call :UpdateConfigManifestFile
if "!UpdateConfigManifestFileReturn!"=="false" (
    set UpdateGeneratedFilesReturn=false
    goto :EOF
)

set UpdateIdlGeneratedHeaderFileReturn=true
call :UpdateIdlGeneratedHeaderFile
if "!UpdateIdlGeneratedHeaderFileReturn!"=="false" (
    set UpdateGeneratedFilesReturn=false
    goto :EOF
)

set UpdateCounterManifestFileReturn=true
call :UpdateCounterManifestFile
if "!UpdateCounterManifestFileReturn!"=="false" (
    set UpdateGeneratedFilesReturn=false
    goto :EOF
)

if "!ResourceDllNeedsRebuild!"=="true" (
    call :BuildResourceDll
    if "!BuildResourceDllResult!"=="false" (
    set UpdateGeneratedFilesReturn=false
    goto :EOF
    )
)

goto :EOF


:: ===========================================================================
:: Update Counter Manifest File
:UpdateCounterManifestFile

echo.
set CHECKEDIN_COUNTER_MANIFEST_FILE=%SrcRoot%\prod\manifests\components\WFPerf.man
set WINFAB_COUNTER_NATIVE_MANIFEST_FILE=%BIN_PATH%\WFPerfNative.man
set WINFAB_COUNTER_SDK_MANIFEST_FILE=%BIN_PATH%\WFPerfSdk.man
set WINFAB_COUNTER_MANIFEST_FILE=%BIN_PATH%\WFPerf.man
set WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT_SDK=%BIN_PATH%\WFPerfDebugSdkOutput.txt
set WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT=%BIN_PATH%\WFPerfDebugOutput.txt

echo Generating Counter Manifest file %WINFAB_COUNTER_MANIFEST_FILE% ...

if "!AllowBreakingPerfCounterChanges!"=="true" (
    %BIN_PATH%\CounterManifestGeneratorManaged.exe %WINFAB_COUNTER_NATIVE_MANIFEST_FILE% %WINFAB_COUNTER_SDK_MANIFEST_FILE% > %WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT_SDK%
    %BIN_PATH%\CounterManifestGeneratorManagedRuntime.exe %WINFAB_COUNTER_SDK_MANIFEST_FILE% %WINFAB_COUNTER_MANIFEST_FILE% > %WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT%
) else (
    %BIN_PATH%\CounterManifestGeneratorManaged.exe %WINFAB_COUNTER_NATIVE_MANIFEST_FILE% %WINFAB_COUNTER_SDK_MANIFEST_FILE% > %WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT_SDK%
    %BIN_PATH%\CounterManifestGeneratorManagedRuntime.exe %WINFAB_COUNTER_SDK_MANIFEST_FILE% %WINFAB_COUNTER_MANIFEST_FILE% %CHECKEDIN_COUNTER_MANIFEST_FILE% > %WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT%
)

set ev=%ERRORLEVEL%
if %ev% neq 0 (
  echo.
  echo FAILED. Counter Manifest generation failed.
  echo Please check %WINFAB_MANIFEST_GENERATOR_DBG_OUTPUT% file for errors.
  echo.

  set UpdateCounterManifestFileReturn=false
  goto :EOF
)

echo Done

echo Comparing generated counter manifest file with checked in file %CHECKEDIN_COUNTER_MANIFEST_FILE% ...
fc %WINFAB_COUNTER_MANIFEST_FILE% %CHECKEDIN_COUNTER_MANIFEST_FILE% >> %COUNTER_MANIFEST_FILE_DIFF%

if ERRORLEVEL 1 (
    echo Updating %CHECKEDIN_COUNTER_MANIFEST_FILE% since it is out-of-date
    copy /y %WINFAB_COUNTER_MANIFEST_FILE% %CHECKEDIN_COUNTER_MANIFEST_FILE%
    set ResourceDllNeedsRebuild=true
    echo.
    echo %CHECKEDIN_COUNTER_MANIFEST_FILE% manifest file updated
    set UpdateCounterManifestFileReturn=true
) else (
    set UpdateCounterManifestFileReturn=true
    echo No update required since %CHECKEDIN_COUNTER_MANIFEST_FILE% is up-to-date.
)
echo .

goto :EOF


:: ===========================================================================
:: Update Trace Manifest File
:UpdateTraceManifestFile

echo.
set CHECKEDIN_MANIFEST_FILE=%SrcRoot%\prod\manifests\components\Microsoft-ServiceFabric-Events.man
set WINFAB_MANIFEST_FILE=%BIN_PATH%\Microsoft-ServiceFabric-Events.man

echo Generating Manifest file %WINFAB_MANIFEST_FILE% ...

:: In SD/razzle environment, this script (and the tools it invokes) was in the PATH environment
:: variable and was found under razzle tools depot. However, in Git, it doesn't exist any more.
:: To mitigate this, we have used a Nuget package that contains these tools and added a razzle_tools
:: environment variable to corext.config. We add this environment variable to PATH temporarily
:: and then revert the PATH to its original value.
set OriginalPath=%PATH%
set PATH=%PATH%;%RAZZLE_TOOLS%;%RAZZLE_TOOLS%\x86

%BIN_PATH%\ManifestGeneratorManaged.exe %WINFAB_MANIFEST_FILE%

set ev=%ERRORLEVEL%
set PATH=%OriginalPath%

if %ev% equ 1 (
  echo.
  echo FAILED. Manifest generation failed.
  echo.

  set UpdateTraceManifestFileReturn=false
  goto :EOF
)

echo Done

echo Comparing generated manifest file with checked in file %CHECKEDIN_MANIFEST_FILE% ...
rep -find:"%BIN_PATH%" -replace:"[BIN_PATH]" %WINFAB_MANIFEST_FILE% > nul
fc %WINFAB_MANIFEST_FILE% %CHECKEDIN_MANIFEST_FILE% >> %MANIFEST_FILE_DIFF%

if ERRORLEVEL 1 (
    echo Updating %CHECKEDIN_MANIFEST_FILE% since it is out-of-date
    copy /y %WINFAB_MANIFEST_FILE% %CHECKEDIN_MANIFEST_FILE%
    set ResourceDllNeedsRebuild=true
    echo.
    echo %CHECKEDIN_MANIFEST_FILE% manifest file updated
    set UpdateTraceManifestFileReturn=true
) else (
    set UpdateTraceManifestFileReturn=true
    echo No update required since %CHECKEDIN_MANIFEST_FILE% is up-to-date.
)

goto :EOF

:: ===========================================================================
:: Update Config Manifest File
:UpdateConfigManifestFile

echo.
set CHECKEDIN_CONFIG_FILE=%SrcRoot%\prod\src\prebuilt\config\EventsRegex.config
set WINFAB_CONFIG_FILE=%BIN_PATH%\EventsRegex.config

echo Generating Config file %WINFAB_CONFIG_FILE% ...

for %%d in (%BIN_PATH%) do set Parent=%%~dpd

set BIN_PARENT=%Parent:~0,-1%%

%BIN_PARENT%\EventsRegexGenerator\EventsRegexGenerator.exe %CHECKEDIN_MANIFEST_FILE% %WINFAB_CONFIG_FILE%
set ev=%ERRORLEVEL%

if ERRORLEVEL 1 (
  echo.
  echo FAILED. Regex generation failed.
  echo.

  set UpdateConfigManifestFileReturn=false
  goto :EOF
)
echo created file %WINFAB_CONFIG_FILE%
echo Done
echo Comparing generated manifest file %WINFAB_CONFIG_FILE% with checked in file %CHECKEDIN_CONFIG_FILE% ...
fc %WINFAB_CONFIG_FILE% %CHECKEDIN_CONFIG_FILE% >> %CONFIG_FILE_DIFF%

if ERRORLEVEL 1 (
    echo Updating %CHECKEDIN_CONFIG_FILE% since it is out-of-date
    copy /y %WINFAB_CONFIG_FILE% %CHECKEDIN_CONFIG_FILE%
    echo.
    echo %CHECKEDIN_CONFIG_FILE% manifest file updated
    set UpdateConfigManifestFileReturn=true
) else (
    set UpdateConfigManifestFileReturn=true
    echo No update required since %CHECKEDIN_CONFIG_FILE% is up-to-date.
)
goto :EOF
:: ===========================================================================
:: Update Idl Generated Header Files
:UpdateIdlGeneratedHeaderFile

echo.
set CHECKEDIN_FILE[1]=%SrcRoot%\prod\src\prebuilt\internal\FabricClient_.h
set GENERATED_FILE[1]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricClient_.h
set CHECKEDIN_FILE[2]=%SrcRoot%\prod\src\prebuilt\internal\FabricCommon_.h
set GENERATED_FILE[2]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricCommon_.h
set CHECKEDIN_FILE[3]=%SrcRoot%\prod\src\prebuilt\internal\FabricImageStore_.h
set GENERATED_FILE[3]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricImageStore_.h
set CHECKEDIN_FILE[4]=%SrcRoot%\prod\src\prebuilt\internal\FabricRuntime_.h
set GENERATED_FILE[4]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricRuntime_.h
set CHECKEDIN_FILE[5]=%SrcRoot%\prod\src\prebuilt\internal\FabricTypes_.h
set GENERATED_FILE[5]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricTypes_.h
set CHECKEDIN_FILE[6]=%SrcRoot%\prod\src\prebuilt\sdk\FabricClient.h
set GENERATED_FILE[6]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricClient.h
set CHECKEDIN_FILE[7]=%SrcRoot%\prod\src\prebuilt\sdk\FabricCommon.h
set GENERATED_FILE[7]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricCommon.h
set CHECKEDIN_FILE[8]=%SrcRoot%\prod\src\prebuilt\sdk\FabricRuntime.h
set GENERATED_FILE[8]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricRuntime.h
set CHECKEDIN_FILE[9]=%SrcRoot%\prod\src\prebuilt\sdk\FabricTypes.h
set GENERATED_FILE[9]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricTypes.h
set CHECKEDIN_FILE[10]=%SrcRoot%\prod\src\prebuilt\internal\FabricInfrastructureService_.h
set GENERATED_FILE[10]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricInfrastructureService_.h
set CHECKEDIN_FILE[11]=%SrcRoot%\prod\src\prebuilt\internal\FabricTokenValidationService_.h
set GENERATED_FILE[11]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricTokenValidationService_.h
set CHECKEDIN_FILE[12]=%SrcRoot%\prod\src\prebuilt\internal\FabricServiceCommunication_.h
set GENERATED_FILE[12]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricServiceCommunication_.h

set CHECKEDIN_FILE[13]=%SrcRoot%\prod\src\prebuilt\internal\FabricClient__i.c
set GENERATED_FILE[13]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricClient__i.c
set CHECKEDIN_FILE[14]=%SrcRoot%\prod\src\prebuilt\internal\FabricCommon__i.c
set GENERATED_FILE[14]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricCommon__i.c
set CHECKEDIN_FILE[15]=%SrcRoot%\prod\src\prebuilt\internal\FabricImageStore__i.c
set GENERATED_FILE[15]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricImageStore__i.c
set CHECKEDIN_FILE[16]=%SrcRoot%\prod\src\prebuilt\internal\FabricInfrastructureService__i.c
set GENERATED_FILE[16]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricInfrastructureService__i.c
set CHECKEDIN_FILE[17]=%SrcRoot%\prod\src\prebuilt\internal\FabricReliableMessaging__i.c
set GENERATED_FILE[17]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricReliableMessaging__i.c
set CHECKEDIN_FILE[18]=%SrcRoot%\prod\src\prebuilt\internal\FabricRuntime__i.c
set GENERATED_FILE[18]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricRuntime__i.c
set CHECKEDIN_FILE[19]=%SrcRoot%\prod\src\prebuilt\internal\FabricServiceCommunication__i.c
set GENERATED_FILE[19]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricServiceCommunication__i.c
set CHECKEDIN_FILE[20]=%SrcRoot%\prod\src\prebuilt\internal\FabricTokenValidationService__i.c
set GENERATED_FILE[20]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricTokenValidationService__i.c
set CHECKEDIN_FILE[21]=%SrcRoot%\prod\src\prebuilt\internal\KPhysicalLog__i.c
set GENERATED_FILE[21]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\KPhysicalLog__i.c

set CHECKEDIN_FILE[22]=%SrcRoot%\prod\src\prebuilt\sdk\FabricClient_i.c
set GENERATED_FILE[22]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricClient_i.c
set CHECKEDIN_FILE[23]=%SrcRoot%\prod\src\prebuilt\sdk\FabricCommon_i.c
set GENERATED_FILE[23]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricCommon_i.c
set CHECKEDIN_FILE[24]=%SrcRoot%\prod\src\prebuilt\sdk\FabricRuntime_i.c
set GENERATED_FILE[24]=%SrcRoot%\prod\src\idl\public\objd\AMD64\FabricRuntime_i.c

set CHECKEDIN_FILE[25]=%SrcRoot%\prod\src\prebuilt\internal\FabricFaultAnalysisService_.h
set GENERATED_FILE[25]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricFaultAnalysisService_.h
set CHECKEDIN_FILE[26]=%SrcRoot%\prod\src\prebuilt\internal\FabricFaultAnalysisService__i.c
set GENERATED_FILE[26]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricFaultAnalysisService__i.c

set CHECKEDIN_FILE[27]=%SrcRoot%\prod\src\prebuilt\internal\FabricUpgradeOrchestrationService_.h
set GENERATED_FILE[27]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricUpgradeOrchestrationService_.h
set CHECKEDIN_FILE[28]=%SrcRoot%\prod\src\prebuilt\internal\FabricTransport_.h
set GENERATED_FILE[28]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricTransport_.h
set CHECKEDIN_FILE[29]=%SrcRoot%\prod\src\prebuilt\internal\fabrictransport__i.c
set GENERATED_FILE[29]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\fabrictransport__i.c

set CHECKEDIN_FILE[30]=%SrcRoot%\prod\src\prebuilt\internal\FabricBackupRestoreService_.h
set GENERATED_FILE[30]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricBackupRestoreService_.h
set CHECKEDIN_FILE[31]=%SrcRoot%\prod\src\prebuilt\internal\FabricBackupRestoreService__i.c
set GENERATED_FILE[31]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricBackupRestoreService__i.c

set CHECKEDIN_FILE[32]=%SrcRoot%\prod\src\prebuilt\internal\SfStatus.h
set GENERATED_FILE[32]=%SrcRoot%\prod\src\data\statuscodes\lib\objd\amd64\SfStatus.h

set CHECKEDIN_FILE[33]=%SrcRoot%\prod\src\prebuilt\internal\FabricContainerActivatorService__i.c
set GENERATED_FILE[33]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricContainerActivatorService__i.c
set CHECKEDIN_FILE[34]=%SrcRoot%\prod\src\prebuilt\internal\FabricContainerActivatorService_.h
set GENERATED_FILE[34]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricContainerActivatorService_.h

set CHECKEDIN_FILE[35]=%SrcRoot%\prod\src\prebuilt\internal\FabricGatewayResourceManager_.h
set GENERATED_FILE[35]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricGatewayResourceManager_.h
set CHECKEDIN_FILE[36]=%SrcRoot%\prod\src\prebuilt\internal\FabricGatewayResourceManager__i.c
set GENERATED_FILE[36]=%SrcRoot%\prod\src\idl\internal\objd\AMD64\FabricGatewayResourceManager__i.c

set IDL_GEN_HEADER_FILE_DIFF=%BINARIES_DIR%\IdlGenHeaderFileDiff.txt
echo Comparing generated header file with idl file:

for %%x in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36) do (
    if exist !GENERATED_FILE[%%x]! (
        echo|set /p=!CHECKEDIN_FILE[%%x]!
        fc !CHECKEDIN_FILE[%%x]! !GENERATED_FILE[%%x]! >> %IDL_GEN_HEADER_FILE_DIFF%
        if ERRORLEVEL 1 (
            echo : out-of-date. Updating.. Please commit this file manually.
            copy !GENERATED_FILE[%%x]! !CHECKEDIN_FILE[%%x]!
        ) else (
            echo : up-to-date.
        )
    ) else (
        echo|set /p=!GENERATED_FILE[%%x]!
        echo : not found. Please fix UpdateGeneratedFiles.cmd.
    )
)

echo.

goto :EOF

:: ===========================================================================
:: Build Resource Dll After Update
:BuildResourceDll
set BuildResourceDllResult=
pushd %SrcRoot%\prod\src\resources\dll

:: Reduce verbosity to console messages relevant to updating manifest files
echo Building resource binary...

set OriginalMsBuildArgs=%MsBuildArgs%
set MsBuildArgs=/verbosity:minimal /nologo

:: Note, this is a debug build. We probably need a command line switch for retail
call build

if ERRORLEVEL 0 (
    set BuildResourceDllResult=true
) else (
    set BuildResourceDllResult=false
)

:: Revert to default
set MsBuildArgs=%OriginalMsBuildArgs%

echo Done building resource binary
goto :EOF


:: ===========================================================================
:: Displays a message to run this script from FabricUnitTests folder
::
:RunFromFabricUnitTestsDirMsg
echo.
echo Please run this script from FabricUnitTests folder under bin
echo E.g. from \rdnext\WindowsFabric\out\debug-amd64\bin\FabricUnitTests
echo.
echo For detailed usage, please type '%~nx0 /?'
echo.

goto :EOF

:: ===========================================================================
:: Print the usage
::
:PrintUsage

echo This script updates the Windows Fabric trace manifest file.
echo Once updated, it shows up as a modified file in Git. Please
echo inspect and commit this file along with your other changes.
echo.
echo The script must be called from a OneBranch (Git/CoreXT4) Window.
echo.
echo Usage: %~nx0 /run
echo.
echo  /run - An argument just to prevent accidental execution of this script
echo  /allowBreakingChangeInCounters - Option to skip compatibility check of MANAGED performance counters. This option is meant to allow breaking changes within a release. 
echo                                   Please ensure that you do not make breaking changes across releases when using this option.
echo. /?   - To view this help
echo.
echo  Example: %~nx0 /run
echo.
goto :EOF